home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_pas / ootp_4 / listobj.pas < prev    next >
Pascal/Delphi Source File  |  1990-03-28  |  8KB  |  307 lines

  1. unit ListObj;
  2.  
  3. {$A+,B-,D+,E+,F-,I+,L+,N-,O-,R-,S+,V+}
  4. {$M 16384,0,655360}
  5.  
  6. interface
  7.  
  8. type
  9.     NodePtr = ^Node;
  10.     ListPtr = ^List;
  11.     ListDemonType = function( pNode : pointer ) : boolean;
  12.  
  13.     List = object
  14.           Head   : NodePtr;
  15.           Tail   : NodePtr;
  16.           Cursor : NodePtr;
  17.           NMem   : integer;
  18.           FindObjectDemon : ListDemonType;
  19.           constructor Init;
  20.           destructor Done;
  21.           procedure Append( pNode : NodePtr );
  22.           procedure Prepend( pNode : NodePtr );
  23.           function PopFirst       : pointer;
  24.           function PopLast        : pointer;
  25.           function PopCursor      : pointer;
  26.           function GetCursor      : pointer;
  27.           function FindObject     : boolean;
  28.           function FindNextObject : boolean;
  29.           end;
  30.  
  31.     Node = object
  32.            pNext : NodePtr;
  33.            Size  : integer;
  34.            procedure Init( ASize : integer );
  35.            procedure AppendToList( var AList : List ) ;
  36.            procedure PrependToList( var AList : List ) ;
  37.            end;
  38.  
  39. function FindAll( pNode :pointer ) : boolean;
  40.  
  41. implementation
  42.  
  43. constructor List.Init;
  44. begin
  45.      Head := nil;
  46.      Tail := nil;
  47.      Cursor := nil;
  48.      NMem := 0;
  49.      FindObjectDemon := FindAll;
  50. end;
  51.  
  52. destructor List.Done;
  53. begin
  54.      while (NMem > 0) and (PopFirst <> nil) do {nothing, just do!};
  55. end;
  56.  
  57. procedure List.Append( pNode : NodePtr );
  58. begin
  59.      if Head = nil then
  60.         begin
  61.         Head := pNode;
  62.         Tail := pNode;
  63.         Inc(NMem);
  64.         end
  65.      else
  66.         begin
  67.         Tail^.pNext := pNode;
  68.         Tail := pNode;
  69.         Inc(NMem);
  70.         end;
  71.      pNode^.pNext := nil;
  72. end;
  73.  
  74. procedure List.Prepend( pNode : NodePtr );
  75. begin
  76.      if Head = nil then
  77.         begin
  78.         Head := pNode;
  79.         Tail := pNode;
  80.         pNode^.pNext := nil;
  81.         Inc(NMem);
  82.         end
  83.      else
  84.         begin
  85.         pNode^.pNext := Head;
  86.         Head := pNode;
  87.         Inc(NMem);
  88.         end;
  89. end;
  90.  
  91.  
  92. function List.PopFirst : pointer;
  93. var
  94.    pFirst : NodePtr;
  95. begin
  96.      if NMem = 1 then begin
  97.         PopFirst := Head;
  98. {        pFirst := Head;
  99.         FreeMem( pFirst, pFirst^.Size );}
  100.         Head := nil;
  101.         Tail := nil;
  102.         Cursor := nil;
  103.         Dec(NMem);
  104.         end
  105.      else
  106.         if NMem > 0 then begin
  107.            PopFirst := Head;
  108. {           pFirst := Head;
  109.            FreeMem( pFirst, pFirst^.Size );}
  110.            if Head <> Tail then begin
  111.               if Cursor = Head then
  112.                  Cursor := Head^.pNext;
  113.               Head := Head^.pNext;
  114.               end;
  115.            Dec(Nmem);
  116.            end
  117.         else begin
  118.             Writeln('ERROR: Attempt to remove element from empty list.');
  119.             PopFirst := nil;
  120.             end;
  121. end;
  122.  
  123.  
  124. function List.PopLast : pointer;
  125. var
  126.    pTempNode : NodePtr;
  127.    pLast     : NodePtr;
  128. begin
  129.      if NMem = 1 then begin
  130.         PopLast := Head;
  131. {        pLast := Head;
  132.         FreeMem( pLast, pLast^.Size );}
  133.         Head := nil;
  134.         Tail := nil;
  135.         Cursor := nil;
  136.         Dec(NMem);
  137.         end
  138.      { if there are members in List }
  139.      else
  140.         if NMem > 0 then begin
  141.            { set pNode to be the Head }
  142.            pTempNode := Head;
  143.            { until we find a node that points at the Tail, keep moving }
  144.            while pTempNode^.pNext <> Tail do
  145.                  pTempNode := pTempNode^.pNext;
  146.            { retrieve the object }
  147.            PopLast := Tail;
  148. {           pLast := Tail;
  149.            FreeMem( pLast, pLast^.Size );}
  150.            { the next-to-last node will point at nothing }
  151.            pTempNode^.pNext := nil;
  152.            { if the Cursor pointed at the old Tail }
  153.            if Cursor = Tail then
  154.               Cursor := pTempNode;
  155.            Tail := pTempNode;
  156.            Dec(Nmem);
  157.            end
  158.         else begin
  159.            Writeln('ERROR: Attempt to remove element from empty list.');
  160.            PopLast := nil;
  161.            end;
  162. end;
  163.  
  164. function List.PopCursor : pointer;
  165. var
  166.    pTempNode : NodePtr;
  167.    pCursor   : NodePtr;
  168. begin
  169.      if NMem = 1 then begin
  170.         PopCursor := Cursor;
  171. {        pCursor := Cursor;
  172.         FreeMem( pCursor, pCursor^.Size );}
  173.         Head := nil;
  174.         Tail := nil;
  175.         Cursor := nil;
  176.         Dec(NMem);
  177.         end
  178.      else if NMem > 0 then begin
  179.              PopCursor := Cursor;
  180. {             pCursor := Cursor;
  181.              FreeMem( pCursor, pCursor^.Size );}
  182.              Dec(Nmem);
  183.              if Cursor <> Head then begin
  184.                 pTempNode := Head;
  185.                 while pTempNode^.pNext <> Cursor do
  186.                       pTempNode := pTempNode^.pNext;
  187.                 { pTempNode points at object in front of Cursor }
  188.                 if Cursor <> Tail then begin
  189.                    { if Cursor is not pointing at Tail of List }
  190.                    { make the object in front of the Cursor point }
  191.                    { to the object in back of the cursor }
  192.                    pTempNode^.pNext := Cursor^.pNext;
  193.                    end
  194.                 else begin
  195.                    { if the Cursor is pointing at the Tail, }
  196.                    { make the object in front of the Cursor point to nil }
  197.                    { and adjust the Tail }
  198.                    pTempNode^.pNext := nil;
  199.                    Tail := pTempNode;
  200.                    end;
  201.                 { set Cursor to point at object in front of itself }
  202.                 Cursor := pTempNode;
  203.                 end
  204.              else begin { if Cursor = Head }
  205.                 Head := Head^.pNext;
  206.                 Cursor := Cursor^.pNext;
  207.                 end
  208.              end
  209.      else begin
  210.         Writeln('ERROR: Attempt to remove element from empty list.');
  211.         PopCursor := nil;
  212.         end;
  213. end;
  214.  
  215. { this function must(!) move the Cursor; since it only returns a pointer }
  216. { to the Cursor's present position, any test to FindNextObject must start }
  217. { with the object after the one currently pointed to by the Cursor (else }
  218. { it will pass the test forever! }
  219. function List.GetCursor : pointer;
  220. begin
  221.      if NMem > 0 then begin
  222.         GetCursor := Cursor;
  223.         { if the Cursor is pointing at the tail, then point it at nil }
  224.         { so that we know we've 'GetCursor'ed the last item in the list }
  225.         if Cursor = Tail then
  226.            Cursor := nil
  227.         else
  228.            Cursor := Cursor^.pNext;
  229.         end
  230.      else
  231.         GetCursor := nil;
  232. end;
  233.  
  234. function List.FindObject : boolean;
  235. begin
  236.      Cursor := Head;
  237.      FindObject := FindNextObject;
  238. end;
  239.  
  240. function List.FindNextObject : boolean;
  241. var FoundStatus, AtEnd : boolean;
  242. begin
  243.      { initialize 'FoundStatus' and 'AtEnd' flags }
  244.      FoundStatus := false;
  245.      AtEnd := false;
  246.      { If there are objects in the list and the Cursor is not nil }
  247.      { (indicating that we did a GetCursor operation on the last object }
  248.      {  in the list) }
  249.      if (NMem > 0) and (Cursor <> nil) then begin
  250.         while (AtEnd = false) and (FoundStatus = false) do begin
  251.               if FindObjectDemon( Cursor ) = true then
  252.                  FoundStatus := true
  253.               else
  254.                  if Cursor^.pNext <> nil then
  255.                     Cursor := Cursor^.pNext
  256.                  else
  257.                     AtEnd := true
  258.         end;
  259.      end;
  260.      FindNextObject := FoundStatus;
  261. end;
  262.  
  263. procedure Node.Init( ASize : integer );
  264. begin
  265.      pNext := nil;
  266.      Size := ASize;
  267. end;
  268.  
  269. procedure Node.AppendToList( var AList : List ) ;
  270. begin
  271.      if AList.Head = nil then begin
  272.         AList.Head := @Self;
  273.         AList.Tail := @Self;
  274.         Inc(AList.NMem)
  275.         end
  276.      else begin
  277.         AList.Tail^.pNext := @Self;
  278.         AList.Tail := @Self;
  279.         Inc(AList.NMem);
  280.      end;
  281.      pNext := nil;
  282. end;
  283.  
  284. procedure Node.PrependToList( var AList : List ) ;
  285. begin
  286.      if AList.Head = nil then begin
  287.         AList.Head := @Self;
  288.         AList.Tail := @Self;
  289.         pNext := nil;
  290.         Inc(AList.NMem)
  291.         end
  292.      else begin
  293.         pNext := AList.Head;
  294.         AList.Head := @Self;
  295.         Inc(AList.NMem);
  296.      end;
  297. end;
  298.  
  299. {$F+}
  300. function FindAll( pNode : pointer ) : boolean;
  301. {$F-}
  302. begin
  303.      FindAll := true;
  304. end;
  305.  
  306. end.
  307.